<template>
  <div
    ref="teldCommentRef"
    :class="[
      'comment-pc teld-comment w-full h-full teld-color-black',
      'flex flex-col relative text-sm bg-white outline-none',
      $q.platform.is.mobile ? 'comment-pc--mobile' : '',
    ]"
  >
    <!-- 顶部标题和数量 -->
    <div
      v-if="showHeader && showHeader !== 'false'"
      class="comment-header py-4 flex justify-between items-center text-base shadow-sm w-full"
      :class="[dense ? 'px-3' : 'px-5']"
    >
      <div
        :title="commentTitle"
        class="comment-header__title flex-1 mr-3 truncate truncate-line-2"
      >
        {{ commentTitle }}
      </div>
      <div class="comment-header__count teld-color-gray text-sm">
        {{ qLangComment.funcCommentCount(totalCommentCount) }}
      </div>
    </div>

    <!-- 评论内容滚动区域 -->
    <div
      ref="commentScrollAreaRef"
      class="flex-1 overflow-y-auto overflow-x-hidden relative w-full outline-none"
      style="max-width: 100%"
    >
      <div
        v-for="comment in commentList"
        :key="comment.ID"
        class="section-comment-with-replies flex"
        :class="[
          dense
            ? 'px-3 py-1'
            : 'px-5 py-3 border-b border-solid border-gray-100',
        ]"
      >
        <!-- 左侧头像 -->
        <div class="left-avatar mr-2" style="">
          <UserAvatar
            :image-url="comment.UserAvatar"
            :data-user-id="comment.UserID"
            class="cursor-pointer"
            @mouseenter="onEnter"
            @mouseleave="onLeave"
          />
        </div>

        <!-- 右侧内容 -->
        <CommentItem
          :data-item="comment"
          @increase="totalCommentCount += 1"
          @decrease="n => (totalCommentCount -= n || 1)"
        />
      </div>

      <template v-if="!isLoading && !commentList.length">
        <template v-if="$slots && $slots.empty">
          <slot name="empty"></slot>
        </template>
        <div
          v-else
          class="teld-comment--empty relative"
          style="top: 50%; margin-top: -50%"
        >
          <div class="teld-color-gray flex justify-center items-center">
            <NoData
              :text="emptyText || qLangComment.noData"
            ></NoData>
          </div>
        </div>
      </template>
    </div>

    <!-- 评论输入框 -->
    <!-- :visible="!isLoading && visible" -->
    <draft-editor
      ref="draftEditorRef"
      :show-avatar="false"
      :is-comment="true"
      :visible="!isLoading && visible"
      :auto-clear-on-hidding="true"
      :offset-parent="teldCommentRef && teldCommentRef.$el"
      class="w-full py-3 border-t border-solid border-gray-200"
      :class="[dense ? 'px-3' : 'px-5']"
      @comment="onComment"
    />

    <!-- 为了便于分辨要选择的人员，这里展示人员信息详情 -->
    <PersonnelInfoPopup
      :model="userInfo"
      :user-id="userId"
      :target-element="targetElement"
      @change-visible="onPopupVisibleChange"
      :class="[disableSelect ? 'select-none' : '']"
    ></PersonnelInfoPopup>

    <!-- loading -->
    <t-inner-loading :showing="isLoading">
      <t-spinner size="28px" color="primary" />
    </t-inner-loading>
  </div>
</template>

<script>
import {
  onBeforeMount,
  onMounted,
  onBeforeUnmount,
  ref,
  provide,
  inject,
} from 'vue';
import UserAvatar from '../components/user-avatar/index.vue';
import CommentItem from './comment-item/index.vue';
import DraftEditor from './draft-editor/index.vue';
import PersonnelInfoPopup from './personnel-info-popup/index.vue';
import NoData from 't/bussiness/repeat/no-data.vue';
// utils
import usePersonnelInfo from './hooks/usePersonnelInfo';
import { scrollPaging } from '../hooks';
import { getCommentList, saveComment } from '../hooks/api';
import { COMMENT_TYPE } from '../utils';

export default {
  name: 'comment-pc',
  inject: ['qLangComment'],
  props: {
    /**
     * 是否显示顶部评论标题和总条数
     */
    showHeader: {
      type: [Boolean, String],
      default: false,
    },
    pageId: {
      type: String,
      default: '',
    },
    dataId: {
      type: String,
      default: '',
    },
    /**
     * 维度
     */
    dimension: {
      type: String,
      default: '',
    },
    commentType: {
      type: Number,
      default: COMMENT_TYPE.DataComment,
    },
    commentTitle: {
      type: String,
      default: '',
    },
    commentReference: {
      type: String,
      default: '',
    },
    // showCommentReference: {
    //   type: Boolean,
    //   default: false,
    // },
    /**透传visible用于点开时给editor赋焦点*/
    visible: {
      type: Boolean,
      default: false,
    },
    /* 无数据时提示文字 */
    emptyText: {
      type: String,
      default: '',
    },
  },
  components: {
    UserAvatar,
    CommentItem,
    DraftEditor,
    PersonnelInfoPopup,
    NoData,
  },
  setup(props, ctx) {
    const teldCommentRef = ref();
    const commentScrollAreaRef = ref();
    const commentList = ref([]);
    const totalCommentCount = ref(0);
    const isLoading = ref(false);
    const hasLoadedAll = ref(false);
    const pageIndex = ref(1);
    const pageSize = ref(20);
    const dense = inject('dense');
    const loginUserInfo = inject('loginUserInfo');
    const notificationLink = inject('notificationLink');
    // const pageUrl = inject('pageUrl');

    console.log('Comment-PC', props, ctx.attrs);
    const {
      userInfo,
      userId,
      targetElement,
      disableSelect,
      showPersonnelInfo,
      hidePersonnelInfo,
      onVisibleChange: onPopupVisibleChange,
    } = usePersonnelInfo();

    // 快捷选人popup定位用的外部容器，用于计算出现在@符号的上下左右位置
    provide('getContainerForPersonnelSelectorPopup', isComment => {
      return isComment ? teldCommentRef.value : commentScrollAreaRef.value;
    });
    provide('showPersonnelInfo', showPersonnelInfo);
    provide('hidePersonnelInfo', hidePersonnelInfo);

    const fetchPageData = async () => {
      isLoading.value = true;

      try {
        // pageId作为接口必须参数
        if (!props.pageId || !props.pageId.trim()) {
          commentList.value = [];
          totalCommentCount.value = 0;
          hasLoadedAll.value = true;
          return;
        }

        const payload = {
          PageID: props.pageId,
          DataID: props.dataId,
          // DataName: props.commentTitle,
          Dimension: props.dimension,
          PageIndex: pageIndex.value,
          PageCount: pageSize.value,
          Sort: 0, // 评论-倒序
        };

        const listRes = await getCommentList(payload);
        console.log('mockData', listRes);
        if (!listRes || listRes.state !== '1' || !listRes.data) {
          // 获取数据失败
          return;
        }
        const { Items, TotalCount, Properties } = listRes.data;
        commentList.value = commentList.value.concat(Items);
        totalCommentCount.value = Properties.UICount;
        pageIndex.value += 1;
        hasLoadedAll.value = commentList.value.length >= TotalCount;
      } catch (error) {
        console.log(error);
      } finally {
        setTimeout(() => {
          isLoading.value = false;
        }, 500);
      }
    };

    const onComment = async draftInfo => {
      const { content, fileList, userIdList, onSucceed, onFail } = draftInfo;
      const newComment = {
        // IsAuthor: true,
        // 接口需要的参数：
        Content: content,
        Dimension: props.dimension, //
        PageID: props.pageId,
        DataID: props.dataId,
        DataName: props.commentTitle,
        ReferenceTitle: props.commentReference,
        CommentType: props.commentType,
        CommentCategory: 0,
        UserAvatar: loginUserInfo.avatar,
        Attachments: fileList.map(n => n.result),
        MentionedUsers: JSON.stringify(userIdList),
        Url: notificationLink(),
        UrlParams: JSON.stringify({
          // fpath: encodeURIComponent(pageUrl),
          showComment: true,
        }),
      };

      try {
        const res = await saveComment(newComment);
        if (!res || res.state !== '1' || !res.data) {
          onFail();
          return;
        }

        // mock new record, and override with real data
        Object.assign(
          newComment,
          {
            ID: 'comment-m-' + parseInt(Math.random() * 1000),
            CommentTime: Date().toLocaleString(),
            UserID: loginUserInfo.userId,
            UserName: loginUserInfo.userName,
            Liked: false,
            LikeCount: 0,
            IsFavorite: false,
            FavoriteCount: 0,
            ReplyCount: 0,
            CanCancel: true,
            IsDeleted: false,
            Replies: [],
          },
          res.data,
        );

        // 评论完将新添加评论展示出来：滚动到顶部
        commentList.value.unshift(newComment);
        const container = commentScrollAreaRef.value;
        container.scrollTop = 0;

        totalCommentCount.value += 1;

        setTimeout(() => {
          // 调接口成功后清空输入框内容
          onSucceed({ focus: true });
        }, 400);
      } catch (error) {
        console.log(error);
        onFail();
      }
    };

    const onEnter = e => {
      showPersonnelInfo({ target: e.target });
    };
    const onLeave = () => {
      hidePersonnelInfo();
    };

    function scrollHanlder() {
      const container = commentScrollAreaRef.value;
      const lastItem = container.querySelector(
        '.section-comment-with-replies:last-child',
      );
      // 提前 300px 获取下一页数据
      scrollPaging(container, lastItem, 300, fetchPageData);
    }
    function onScroll(e) {
      const { deltaY } = e;
      if (
        deltaY < 0 ||
        !commentList.value ||
        !commentList.value.length ||
        isLoading.value ||
        hasLoadedAll.value
      ) {
        // 滚向顶部时、没有数据时、正在加载数据时、及全部加载完时，滚动无需处理
        return;
      }
      requestAnimationFrame(scrollHanlder);
    }

    onBeforeMount(() => {
      if (!props.pageId) {
        throw new Error('pageId is required');
      }
      if (props.commentType == COMMENT_TYPE.DataComment && !props.dataId) {
        throw new Error('dataId is required when commentType is 0.DataComment');
      }
      fetchPageData();
    });
    onMounted(() => {
      const scrollArea = commentScrollAreaRef.value;
      if (scrollArea) {
        scrollArea.addEventListener('wheel', onScroll, true);
      }
    });
    onBeforeUnmount(() => {
      const scrollArea = commentScrollAreaRef.value;
      scrollArea && scrollArea.removeEventListener('wheel', onScroll);
    });

    return {
      teldCommentRef,
      commentScrollAreaRef,
      isLoading,
      commentList,
      totalCommentCount,
      //
      dense,
      userInfo,
      userId,
      targetElement,
      disableSelect,
      showPersonnelInfo,
      hidePersonnelInfo,
      onPopupVisibleChange,
      //
      onEnter,
      onLeave,
      onComment,
    };
  },
};
</script>

<style>
.comment-pc--mobile {
  max-width: 100vw;
}
</style>
